_version_code = "0.1.2"

import pygame
import math
from os.path import join as pjoin

# 初始化pygame
pygame.init()

# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
YELLOW = (255, 255, 0)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
GRAY = (128, 128, 128)

# 六边形参数
HEX_RADIUS = 25
HEX_WIDTH = HEX_RADIUS * 2
HEX_HEIGHT = math.sqrt(3) * HEX_RADIUS
HEX_VERTICES = 6

# 全局棋子类型列表
PIECE_TYPES = [
    {"id": 0, "name": "Master", "hp": 3, "atk": 0, "attack_range": 1, "mp": 1, "cost": 12, "icon_path": "master_icon.png"},
    {"id": 1, "name": "Saber", "hp": 9, "atk": 3, "attack_range": 1, "mp": 3, "cost": 3, "icon_path": "saber_icon.png"},
    {"id": 2, "name": "Archer", "hp": 7, "atk": 2, "attack_range": 2, "mp": 3, "cost": 3, "icon_path": "archer_icon.png"},
    {"id": 3, "name": "Caster", "hp": 6, "atk": 6, "attack_range": 2, "mp": 2, "cost": 5, "icon_path": "caster_icon.png"},
    {"id": 4, "name": "Rider", "hp": 8, "atk": 4, "attack_range": 2, "mp": 5, "cost": 5, "icon_path": "knight_icon.png"},
    {"id": 5, "name": "Assassin", "hp": 4, "atk": 7, "attack_range": 1, "mp": 4, "cost": 5, "icon_path": "assassin_icon.png"},
    {"id": 6, "name": "Priest", "hp": 6, "atk": -2, "attack_range": 2, "mp": 3, "cost": 4, "icon_path": "priest_icon.png"},
    {"id": 7, "name": "Druid", "hp": 6, "atk": 6, "attack_range": 4, "mp": 2, "cost": 6, "icon_path": "druid_icon.png"},
    # {"id": 8, "name": "Guard", "hp": 10, "atk": 2, "attack_range": 1, "mp": 2, "cost": 6, "icon_path": "guard_icon.png"}
]

# 地图尺寸
MAP_ROWS = 20
MAP_COLS = 20

# 根据地图尺寸动态调整屏幕尺寸
SCREEN_WIDTH = int(HEX_RADIUS * math.sqrt(3) * (MAP_COLS + 1)) + 300  # 地图宽度 + 提示区宽度
SCREEN_HEIGHT = int(HEX_RADIUS * 3/2 * (MAP_ROWS + 1))  # 地图高度
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Hexagonal Chess Game")

class Hexagon:
    def __init__(self, col, row):
        self.col = col
        self.row = row
        self.center = self.get_center()
        self.vertices = self.get_vertices()
        self.is_selected = False
        self.is_moveable = False
        self.is_attackable = False

    def get_center(self):
        """计算六边形的中心点坐标"""
        # 调整中心点计算以实现六边形密铺
        x = HEX_RADIUS * math.sqrt(3) * (self.col + 0.5 * (self.row % 2))
        y = HEX_RADIUS * 3/2 * self.row
        return x, y

    def get_vertices(self):
        """计算六边形的顶点坐标"""
        vertices = []
        for i in range(HEX_VERTICES):
            angle = math.pi / 3 * (i + 0.5)  # 调整角度以适应 pointy top
            x = self.center[0] + HEX_RADIUS * math.cos(angle)
            y = self.center[1] + HEX_RADIUS * math.sin(angle)
            vertices.append((x, y))
        return vertices

    def draw(self, screen):
        """在屏幕上绘制六边形"""
        if self.is_selected:
            pygame.draw.polygon(screen, YELLOW, self.vertices)
        elif self.is_moveable:
            pygame.draw.polygon(screen, BLUE, self.vertices)
        elif self.is_attackable:
            pygame.draw.polygon(screen, RED, self.vertices)
        else:
            pygame.draw.polygon(screen, WHITE, self.vertices)
        pygame.draw.polygon(screen, BLACK, self.vertices, 2)

    def distance_to(self, other_hexagon):
        """计算两个六边形之间的距离"""
        delta_row = self.row - other_hexagon.row
        delta_col = self.col - other_hexagon.col - self.row // 2 + other_hexagon.row // 2
        if delta_row * delta_col > 0:
            return abs(delta_row + delta_col)
        else:
            return (abs(delta_row + delta_col) + abs(delta_row - delta_col)) // 2

class Piece:
    def __init__(self, id, player):
        self.piece_id = None
        self.type_id = id
        self.name = PIECE_TYPES[id]["name"]
        self.hp = PIECE_TYPES[id]["hp"]
        self.atk = PIECE_TYPES[id]["atk"]
        self.attack_range = PIECE_TYPES[id]["attack_range"]
        self.mp = PIECE_TYPES[id]["mp"]
        self.cost = PIECE_TYPES[id]["cost"]
        icon_path = PIECE_TYPES[id]["icon_path"]
        self.icon = pygame.image.load(pjoin("icons", icon_path)).convert_alpha()
        # 缩放图标以适应六边形网格
        icon_size = int(HEX_RADIUS * 1.8)
        self.icon = pygame.transform.scale(self.icon, (icon_size, icon_size))
        self.player = player
        self.position = None

    def move(self, hexagon):
        """移动棋子到指定的六边形"""
        if self.mp > 0:
            self.mp -= self.distance_to(hexagon)
            self.position = hexagon

    def attack(self, target):
        """攻击目标棋子"""
        if self.position and self.attack_range >= self.distance_to(target.position):
            if target.name == "Master":
                target.hp -= 1  # Master 受到的所有伤害固定为 1
            else:
                target.hp -= self.atk
            if target.hp <= 0:
                target.player.pieces.remove(target)
                if target.name == "Master":
                    return True
            elif target.hp > PIECE_TYPES[target.type_id]["hp"]:
                target.hp = PIECE_TYPES[target.type_id]["hp"]  # 防止血量超过最大值
            self.mp = 0
        return False

    def distance_to(self, hexagon):
        """计算棋子到指定六边形的距离"""
        delta_row = self.position.row - hexagon.row
        delta_col = self.position.col - hexagon.col - self.position.row//2 + hexagon.row//2
        if delta_row * delta_col > 0:
            return abs(delta_row + delta_col)
        else:
            return (abs(delta_row + delta_col) + abs(delta_row - delta_col)) // 2
        
    def draw_hp(self, screen, hexagon):
        """在棋子的右上方绘制血量角标"""
        font = pygame.font.Font(None, 20)  # 使用较小的字体
        hp_text = font.render(str(self.hp), True, RED)  # 血量显示为红色
        text_rect = hp_text.get_rect()
        # 将血量角标放置在棋子的右上方
        text_rect.topleft = (hexagon.center[0] + HEX_RADIUS // 2, hexagon.center[1] - HEX_RADIUS // 2)
        screen.blit(hp_text, text_rect)

    def draw_highlight(self, screen, hexagon):
        """在棋子周围绘制高亮边框"""
        pygame.draw.polygon(screen, GREEN, hexagon.vertices, 5)

class Player:
    def __init__(self, id, color):
        self.id = id
        self.color = color
        # 初始化 Master 棋子
        self.master = Piece(0, self)
        self.pieces = [self.master]  # 初始化玩家拥有的棋子列表
        self.cost = 5  # 初始化 cost

    def add_piece(self, type_id, hexagon):
        """添加一个新的棋子到指定的六边形"""
        piece = Piece(type_id, self)
        piece.position = hexagon
        self.pieces.append(piece)
        self.cost -= piece.cost

class Game:
    def __init__(self):
        self.font = pygame.font.Font(None, 36)
        self.players = [Player(1, WHITE), Player(2, BLACK)]  # 初始化玩家列表，创建两个玩家对象
        self.current_player = self.players[0]
        self.map = self.create_map()
        self.selected_piece = None
        self.selected_piece_to_place = None  # piece_data["id"]
        self.turn_number = 1
        self.ok_to_draw_psm = False  # 是否允许绘制 Piece Selection Menu
        self.piece_box_height = 60  # 每个棋子的方格高度

        # 创建地图和提示区的 Surface 对象
        self.map_surface = pygame.Surface((SCREEN_WIDTH - 400, SCREEN_HEIGHT))  # 地图区域
        self.info_surface = pygame.Surface((400, SCREEN_HEIGHT))  # 提示区域

        # 设置提示区的背景颜色
        self.info_surface.fill(WHITE)

        self.game_over = False  # 添加游戏结束标志
        self.show_start_screen = True  # 添加开始界面标志
        self.start_button_pressed = False  # 添加按键按下标志
        self.next_turn_button_pressed = False  # 添加按键按下标志
        self.show_fog_of_war = True  # 初始状态为 True，按钮颜色为蓝色

    def create_map(self):
        """创建游戏地图"""
        map = {}
        # 绘制指定数量的六边形棋盘
        for row in range(20):
            for col in range(20):
                hexagon = Hexagon(col, row)
                map[(col, row)] = hexagon
        # Notice: 设置Master位置
        self.players[0].master.position = map[(10, 13)]
        self.players[1].master.position = map[(10, 5)]
        return map

    def draw(self, screen):
        """绘制游戏界面"""
        # 清空地图和提示区
        self.map_surface.fill(WHITE)
        self.info_surface.fill(WHITE)

        # 绘制可移动范围
        self.draw_moveable_hexagons()
        
        # 绘制地图
        for hexagon in self.map.values():
            hexagon.draw(self.map_surface)

        # 绘制所有棋子
        adjust_value = 3
        for player in self.players:
            for piece in player.pieces:
                if piece.position:
                    if piece == player.master and player == self.current_player:
                        piece.draw_highlight(self.map_surface, piece.position)
                    self.map_surface.blit(piece.icon, 
                                          (piece.position.center[0] - HEX_RADIUS + adjust_value, 
                                           piece.position.center[1] - HEX_RADIUS + adjust_value))
                    # 绘制血量角标
                    piece.draw_hp(self.map_surface, piece.position)

        # 绘制视野范围
        if self.show_fog_of_war:
            self.draw_fog_of_war()

        # 绘制提示区
        self.draw_info_section()
        
        # 将地图和提示区绘制到主屏幕上
        screen.blit(self.map_surface, (0, 0))
        screen.blit(self.info_surface, (SCREEN_WIDTH - 400, 0))

        # 绘制边框
        pygame.draw.rect(screen, BLACK, (0, 0, SCREEN_WIDTH - 400, SCREEN_HEIGHT), 2)  # 地图边框
        pygame.draw.rect(screen, BLACK, (SCREEN_WIDTH - 400, 0, 400, SCREEN_HEIGHT), 2)  # 提示区边框

        pygame.display.flip()

    def draw_moveable_hexagons(self):
        """绘制可移动的六边形"""
        for hexagon in self.map.values():
            if hexagon.is_moveable:
                pygame.draw.polygon(self.map_surface, BLUE, hexagon.vertices)

    def get_visible_hexagons(self):
        """获取当前玩家所有棋子的视野范围"""
        visible_hexagons = set()
        for piece in self.current_player.pieces:
            visible_hexagons.add(piece.position)  # 棋子自身的位置可见
            if piece.name == "Master":
                visible_hexagons.update(self.get_adjacent_hexagons(piece.position))  # Master 周围相邻的六个六边形格
            else:
                for hexagon in self.map.values():
                    if 1 <= piece.distance_to(hexagon) <= piece.attack_range:
                        visible_hexagons.add(hexagon)
        return visible_hexagons

    def draw_fog_of_war(self):
        """绘制视野范围"""
        visible_hexagons = self.get_visible_hexagons()
        for hexagon in self.map.values():
            if hexagon not in visible_hexagons:
                pygame.draw.polygon(self.map_surface, GRAY, hexagon.vertices)
                pygame.draw.polygon(self.map_surface, BLACK, hexagon.vertices, 2)  # 保留六边形网格

    def get_adjacent_hexagons(self, hexagon):
        """获取相邻的六边形"""
        adjacent_hexagons = []
        directions = [(1, 0), (-1, 0), (0, 1), (0, -1), (1, -1), (1, 1), (-1, -1), (-1, 1)]
        for direction in directions:
            col = hexagon.col + direction[0]
            row = hexagon.row + direction[1]
            if (col, row) in self.map and self.map[(col, row)].distance_to(hexagon) == 1:
                adjacent_hexagons.append(self.map[(col, row)])
        return adjacent_hexagons

    def draw_info_section(self):
        """绘制提示区"""
        y_offset = 20
        # 判断游戏是否结束
        if self.game_over:
            text = self.font.render("Game Over!", True, BLACK)
            self.info_surface.blit(text, (20, y_offset))
            y_offset += 20
            text = self.font.render(f"Player {self.players[0].id} is winner!", True, BLACK)
            self.info_surface.blit(text, (20, y_offset))
            # 绘制“结束游戏”按钮
            button_rect = pygame.Rect(20, SCREEN_HEIGHT - 60, 360, 40)  # 按钮位置和大小
            pygame.draw.rect(self.info_surface, BLUE, button_rect)  # 按钮背景颜色
            text = self.font.render("Game Over", True, WHITE)  # 按钮文本
            text_rect = text.get_rect(center=button_rect.center)
            self.info_surface.blit(text, text_rect)
            return
        
        # 绘制当前玩家和回合信息
        text = self.font.render(f"Player: {self.current_player.id}, Turn: {self.turn_number}", True, BLACK)
        self.info_surface.blit(text, (20, y_offset))
        y_offset += 40

        # 绘制被选中棋子的信息
        if self.selected_piece:
            piece=self.selected_piece
            if piece.name == "Master":
                piece_info = f"Name: {piece.name},HP: {piece.hp},Total Cost: {self.current_player.cost},MP: {piece.mp}"
            else:
                piece_info = f'Name: {piece.name},Cost: {piece.cost},HP: {piece.hp},MP: {piece.mp},ATK: {piece.atk}'
            
            # 渲染多行文本
            for line in piece_info.split(','):
                text = self.font.render(line, True, BLACK)
                self.info_surface.blit(text, (20, y_offset))
                y_offset += 30  # 行间距
        
        # 进入放置棋子选择界面
        if self.ok_to_draw_psm:
            self.draw_piece_selection_menu(y_offset)  # 传递当前的 y_offset 值

        # 绘制“下一回合”按钮
        button_rect = pygame.Rect(20, SCREEN_HEIGHT - 60, 360, 40)
        button_color = RED if self.next_turn_button_pressed else BLUE
        pygame.draw.rect(self.info_surface, button_color, button_rect)
        text = self.font.render("Next Turn", True, WHITE)
        text_rect = text.get_rect(center=button_rect.center)
        self.info_surface.blit(text, text_rect)

        # 绘制“切换视野”按钮
        toggle_fog_button_rect = pygame.Rect(20, SCREEN_HEIGHT - 120, 360, 40)
        button_color = BLUE if self.show_fog_of_war else GREEN 
        pygame.draw.rect(self.info_surface, button_color, toggle_fog_button_rect)
        toggle_fog_text = self.font.render("Toggle Fog of War", True, WHITE)
        toggle_fog_text_rect = toggle_fog_text.get_rect(center=toggle_fog_button_rect.center)
        self.info_surface.blit(toggle_fog_text, toggle_fog_text_rect)

    def draw_piece_selection_menu(self, start_y):
        """绘制棋子选择菜单"""
        y_offset = start_y  # 使用传递进来的 start_y 值
        id = 0
        for piece_data in PIECE_TYPES[1:]:  # 遍历全局棋子类型列表
            id += 1
            name=piece_data["name"]
            hp=piece_data["hp"]
            atk=piece_data["atk"]
            mp=piece_data["mp"]
            cost=piece_data["cost"]
            icon_path=piece_data["icon_path"]
            icon = pygame.image.load(pjoin("icons", icon_path)).convert_alpha()
            icon_size = int(HEX_RADIUS * 1.8)  # 设置图标大小
            icon = pygame.transform.scale(icon, (icon_size, icon_size))
            
            # 绘制棋子方格背景
            icon_rect = pygame.Rect(20, y_offset, 350, self.piece_box_height)
            if self.selected_piece_to_place == id:
                pygame.draw.rect(self.info_surface, BLUE, icon_rect)  # 高亮选中方格
            elif self.current_player.cost < cost:
                pygame.draw.rect(self.info_surface, GRAY, icon_rect)  # 不可放置方格变暗
            else:
                pygame.draw.rect(self.info_surface, WHITE, icon_rect)  # 正常方格
            
            # 绘制棋子图标和名称
            self.info_surface.blit(icon, (25, y_offset + 5))  # Notice: 参数设置引起显示冲突
            text = self.font.render(f"{name} (Cost: {cost})", True, BLACK)
            self.info_surface.blit(text, (70, y_offset + 5))
            
            # 绘制棋子的HP、ATK、MP信息
            info_text = self.font.render(f"HP: {hp}, ATK: {atk}, MP: {mp}", True, BLACK)
            self.info_surface.blit(info_text, (70, y_offset + 30))
            
            y_offset += self.piece_box_height  # 动态调整行间距

    def draw_start_screen(self, screen):
        """绘制开始界面"""
        screen.fill(WHITE)
        font = pygame.font.Font(None, 74)
        text = font.render("ChessPlus Game", True, BLACK)
        text_rect = text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 - 50))
        screen.blit(text, text_rect)

        button_rect = pygame.Rect(SCREEN_WIDTH // 2 - 100, SCREEN_HEIGHT // 2 + 50, 200, 50)
        button_color = RED if self.start_button_pressed else BLUE
        pygame.draw.rect(screen, button_color, button_rect)
        text = font.render("Start", True, WHITE)
        text_rect = text.get_rect(center=button_rect.center)
        screen.blit(text, text_rect)
        # 绘制版本号
        font = pygame.font.Font(None, 25)
        text = font.render("Ver. "+_version_code, True, BLACK)
        text_rect = text.get_rect(bottomright=(SCREEN_WIDTH, SCREEN_HEIGHT))
        screen.blit(text, text_rect)

        pygame.display.flip()

    def run(self):
        """运行游戏主循环"""
        clock = pygame.time.Clock()
        running = True
        while running:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False
                elif event.type == pygame.MOUSEBUTTONDOWN:
                    mouse_pos = pygame.mouse.get_pos()
                    if self.show_start_screen:
                        button_rect = pygame.Rect(SCREEN_WIDTH // 2 - 100, SCREEN_HEIGHT // 2 + 50, 200, 50)
                        if button_rect.collidepoint(mouse_pos):
                            self.start_button_pressed = True
                            self.draw_start_screen(screen)
                            pygame.time.wait(100)  # 等待0.1秒
                            self.show_start_screen = False
                            self.start_button_pressed = False
                    else:
                        if mouse_pos[0] < SCREEN_WIDTH - 400:  # 点击地图区域
                            for hexagon in self.map.values():
                                if self.is_point_in_hexagon(mouse_pos, hexagon):
                                    if event.button == 1:  # 左键点击
                                        self.handle_left_click(hexagon)
                                    elif event.button == 3:  # 右键点击
                                        self.handle_right_click(hexagon)
                                    break
                        else:  # 点击提示区域
                            self.handle_info_section_click(mouse_pos)
            if self.show_start_screen:
                self.draw_start_screen(screen)
            else:
                self.draw(screen)
            clock.tick(60)
        pygame.quit()

    def is_point_in_hexagon(self, point, hexagon):
        """判断一个点是否在六边形内部"""
        x, y = point
        center_x, center_y = hexagon.center
        # 计算点到六边形中心的距离
        dx = abs(x - center_x)
        dy = abs(y - center_y)
        # 如果点在六边形的外接矩形之外，直接返回False
        if dx > HEX_RADIUS * math.sqrt(3) / 2 or dy > HEX_RADIUS:
            return False
        # 使用六边形的几何特性判断点是否在内部
        return dx <= (HEX_RADIUS * math.sqrt(3) / 2 - dy * math.sqrt(3) / 3)

    def handle_info_section_click(self, mouse_pos):
        """处理提示区的点击事件"""
        if self.selected_piece and self.selected_piece.name == "Master":
            # 计算点击位置在提示区内的相对坐标
            relative_x = mouse_pos[0] - (SCREEN_WIDTH - 400)
            relative_y = mouse_pos[1]

            # 检查是否点击了棋子选择菜单
            start_y = 180  # Notice: 手动确定值
            for piece_data in PIECE_TYPES[1:]:
                icon_rect = pygame.Rect(20, start_y, 200, self.piece_box_height)
                if icon_rect.collidepoint(relative_x, relative_y):
                    if self.selected_piece_to_place == piece_data["id"]:
                        # 取消选择
                        self.selected_piece_to_place = None
                    elif self.current_player.cost >= piece_data["cost"]:
                        # 标记待放置
                        self.selected_piece_to_place = piece_data["id"]
                    return
                start_y += self.piece_box_height

        # 检查是否点击了“下一回合”按钮
        button_rect = pygame.Rect(SCREEN_WIDTH - 400 + 20, SCREEN_HEIGHT - 60, 360, 40)  # Notice: 手动确定值
        if button_rect.collidepoint(mouse_pos):
            self.next_turn_button_pressed = True
            self.draw(screen)
            pygame.display.update()  # 更新显示
            pygame.time.wait(100)  # 等待0.1秒
            self.next_turn_button_pressed = False
            self.next_turn()

        # 检查是否点击了“视野切换”按钮
        toggle_fog_button_rect = pygame.Rect(SCREEN_WIDTH - 400 + 20, SCREEN_HEIGHT - 120, 360, 40)  # Notice: 手动确定值
        if toggle_fog_button_rect.collidepoint(mouse_pos):
            self.show_fog_of_war = not self.show_fog_of_war
            self.draw(screen)
            pygame.display.update()  # 更新显示

    def next_turn(self):
        """切换到下一回合"""
        if self.game_over:
            pygame.event.post(pygame.event.Event(pygame.QUIT))  # 触发退出事件
            return

        self.deselect_piece()
        for piece in self.current_player.pieces:
            piece.mp = PIECE_TYPES[piece.type_id]["mp"]
        self.current_player.cost += 2

        # 切换到下一名玩家
        while True:
            self.current_player = self.players[self.turn_number % len(self.players)]
            if self.current_player.master is not None:  # 跳过失败的玩家
                break
        self.turn_number += 1

    def handle_left_click(self, hexagon):
        """处理左键点击事件"""
        if self.selected_piece:
            if hexagon.is_moveable:
                self.selected_piece.move(hexagon)
                self.selected_piece = None
            self.deselect_piece()
        else:
            piece = self.get_piece_at(hexagon)
            if piece and piece.player == self.current_player:
                self.select_piece(piece, hexagon, mode='move')

    def handle_right_click(self, hexagon):
        """处理右键点击事件"""
        if self.selected_piece:
            if hexagon.is_attackable:
                # 右键放置选中的棋子
                if self.selected_piece.name == "Master":
                    if self.selected_piece_to_place:
                        self.current_player.add_piece(self.selected_piece_to_place, hexagon)
                        self.selected_piece_to_place = None
                        self.selected_piece.mp = 0
                # 右键攻击
                else:
                    piece=self.get_piece_at(hexagon)
                    if self.selected_piece.attack(piece):  # 本次攻击击败Master
                        self.players.remove(piece.player)  # 移除失败的Master
                        piece.player.pieces = []  # 移除所有棋子
                        # 判断游戏是否结束
                        if len(self.players) == 1:
                            self.game_over = True
                    self.selected_piece = None
            self.deselect_piece()
        else:
            piece = self.get_piece_at(hexagon)
            if piece and piece.player == self.current_player:
                self.select_piece(piece, hexagon, mode='attack')

    def select_piece(self, piece, hexagon, mode):
        """选择一个棋子"""
        self.selected_piece = piece
        hexagon.is_selected = True
        if piece.mp:
            if mode == 'move':
                self.calculate_moveable_hexagons()
            elif mode == 'attack':
                self.calculate_attackable_hexagons()

    def deselect_piece(self):
        """取消选择棋子"""
        self.selected_piece = None
        self.ok_to_draw_psm = False
        self.selected_piece_to_place = None
        for hexagon in self.map.values():
            hexagon.is_selected = False
            hexagon.is_moveable = False
            hexagon.is_attackable = False

    def calculate_moveable_hexagons(self):
        """计算可移动的六边形"""
        visible_hexagons = self.get_visible_hexagons()
        for hexagon in self.map.values():
            if 1 <= self.selected_piece.distance_to(hexagon) <= self.selected_piece.mp:
                if not self.get_piece_at(hexagon) and hexagon in visible_hexagons:
                    hexagon.is_moveable = True

    def calculate_attackable_hexagons(self):
        """计算可攻击的六边形"""
        if self.selected_piece.name == "Master":
            self.ok_to_draw_psm = True
            for hexagon in self.map.values():
                if self.selected_piece.distance_to(hexagon) == 1 and not self.get_piece_at(hexagon):
                    hexagon.is_attackable = True
        # Druid
        elif self.selected_piece.name == "Druid":
            for hexagon in self.map.values():
                distance = self.selected_piece.distance_to(hexagon)
                if 3 <= distance <= 4:
                    piece = self.get_piece_at(hexagon)
                    if piece and piece.player != self.selected_piece.player:
                        hexagon.is_attackable = True
        # Priest
        elif self.selected_piece.name == "Priest":
            for hexagon in self.map.values():
                if 1 <= self.selected_piece.distance_to(hexagon) <= self.selected_piece.attack_range:
                    piece = self.get_piece_at(hexagon)
                    # 同玩家、非Master、生命值小于最大值
                    if piece and piece.player == self.selected_piece.player and piece.name != "Master" and piece.hp < piece.type_id["hp"]:
                        hexagon.is_attackable = True
        else:
            for hexagon in self.map.values():
                if 1 <= self.selected_piece.distance_to(hexagon) <= self.selected_piece.attack_range:
                    piece = self.get_piece_at(hexagon)
                    if piece and piece.player != self.selected_piece.player:
                        hexagon.is_attackable = True

    def get_piece_at(self, hexagon):
        """获取指定六边形上的棋子"""
        for player in self.players:
            for piece in player.pieces:
                if piece.position == hexagon:
                    return piece
        return None
    
if __name__ == "__main__":
    game = Game()
    game.run()